//
//  NSAttributedString+Extensions.swift
//  FrameProduct
//
//  Created by delegate on 2024/2/3.
//


import UIKit

public extension NSAttributedString {

    func width(considering height: CGFloat) -> CGFloat {

        let constraintBox = CGSize(width: .greatestFiniteMagnitude, height: height)
        let rect = self.boundingRect(
            with: constraintBox,
            options: [.usesLineFragmentOrigin, .usesFontLeading],
            context: nil
        )
        return rect.width
    }
    
    static func bold(_ text: String, size: CGFloat = 11, color: UIColor = .black) -> NSAttributedString {
        let attrs: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: size),
            NSAttributedString.Key.foregroundColor : color
        ]
        return NSAttributedString(string: text, attributes: attrs)
    }
    
    static func italic(_ text: String, size: CGFloat = 11, color: UIColor = .black) -> NSAttributedString {
        let attrs: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font : UIFont.italicSystemFont(ofSize: size),
            NSAttributedString.Key.foregroundColor : color
        ]
        return NSAttributedString(string: text, attributes: attrs)
    }
    
    static func normal(_ text: String, size: CGFloat = 11, color: UIColor = .black) -> NSAttributedString {
        let attrs: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font : UIFont.systemFont(ofSize: size),
            NSAttributedString.Key.foregroundColor : color
        ]
        return NSAttributedString(string: text, attributes: attrs)
    }
    
    /// 根据限定的maxWidth，分割每一行的富文本
    ///
    /// - parameter maxWidth:  限定文本显示的宽度
    /// - returns: 分割的每一行的富文本
    func splitLines(with maxWidth: CGFloat) -> [NSAttributedString] {
        
        let frameSetter = CTFramesetterCreateWithAttributedString(self)
        let path = CGMutablePath()
        path.addRect(CGRect(x: 0, y: 0, width: maxWidth, height: 100000))
        
        let frame = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: 0), path, nil)
        let lines = CTFrameGetLines(frame) as? [CTLine]
        var point = CGPoint.zero
//        CGPoint lineOrigins[CFArrayGetCount(lines)];
        CTFrameGetLineOrigins(frame,  CFRangeMake(0, 0), &point)
        return lines?.map { line -> NSAttributedString in
            let lineRange = CTLineGetStringRange(line)
            let range = NSRange(location: lineRange.location, length: lineRange.length)
            let sub = self.attributedSubstring(from: range)
            
//            var lineAscent: CGFloat = 0//上行行高
//            var lineDescent: CGFloat = 0 //下行行高
//            var lineLeading: CGFloat = 0//行距
//            var lineHeight: CGFloat = 0//行高
              //获取每行的高度
//            CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading)
//            lineHeight = lineAscent +  abs(lineDescent) + lineLeading
            return sub
        } ?? []
    }
    
    /// 根据限定的maxWidth、maxLines 生成新的富文本，被切割的结尾用...展示
    ///
    /// - parameter maxLines:  限定文本最大行数
    /// - parameter maxWidth:  限定文本显示的宽度
    /// - parameter tailWidth:  尾部预留的宽度，用于扩展展开或者收起的宽度
    /// - parameter isIntact:  返回的富文本是否是完整未经处理的
    /// - returns: 分割的每一行的富文本
    func split(with maxLines: Int, maxWidth: CGFloat, tailWidth: CGFloat, isIntact: inout Bool) -> NSAttributedString {
        isIntact = true
        if maxLines == 0 {
            return self
        }
        let att = NSMutableAttributedString()
        let lines = splitLines(with: maxWidth)
        // 获取最后一行文本的内容，让其只显示一部分
        if lines.count >= maxLines {
            var lastLine = lines[maxLines - 1]
            let width = lastLine.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: CGFloat(MAXFLOAT)), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).width
            // 展开的宽度和...的宽度
            let margin: CGFloat = tailWidth + 10 // 10是3个点的宽度
            let maxWidthOfLastLine = maxWidth - margin
            if width > maxWidthOfLastLine {
                let newLines = lastLine.splitLines(with: maxWidthOfLastLine)
                let firstine = NSMutableAttributedString(attributedString: newLines[0])
                firstine.append(NSAttributedString(string: "...", attributes: [.font: UIFont.systemFont(ofSize: 16)]))
                lastLine = firstine
                isIntact = false
                // 重新拼接富文本
                for i in 0..<maxLines {
                    var line = lines[i]
                    if i == maxLines - 1 {
                        line = lastLine
                    }
                    att.append(line)
                }
                
                
                return att
            }
        }
        return self
    }
}

public extension NSMutableAttributedString {
    
    @discardableResult
    func bold(_ text: String, size: CGFloat = 11, color: UIColor = .black) -> NSMutableAttributedString {
        let attrs: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: size),
            NSAttributedString.Key.foregroundColor : color
        ]
        let boldString = NSMutableAttributedString(string: text, attributes: attrs)
        self.append(boldString)
        return self
    }
    
    @discardableResult
    func italic(_ text: String, size: CGFloat = 11, color: UIColor = .black) -> NSMutableAttributedString {
        let attrs: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font : UIFont.italicSystemFont(ofSize: size),
            NSAttributedString.Key.foregroundColor : color
        ]
        let boldString = NSMutableAttributedString(string: text, attributes: attrs)
        self.append(boldString)
        return self
    }
    
    @discardableResult
    func normal(_ text: String, font: UIFont = .systemFont(ofSize: 11), color: UIColor = .black) -> NSMutableAttributedString {
        let attrs: [NSAttributedString.Key: Any] = [
            NSAttributedString.Key.font : font,
            NSAttributedString.Key.foregroundColor : color
        ]
        let normal =  NSMutableAttributedString(string: text, attributes: attrs)
        self.append(normal)
        return self
    }
    
}

